package no.hio.wsclient.dao;


import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

import no.hio.wsclient.vo.ProductStock;
import no.hio.wsproviderproduct.Product;
import no.hio.wsproviderstock.StockItem;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

import static org.easymock.EasyMock.*;

public class ProductStockDAOImplTestCase {

	ProductStockDAO dao;
	ProductDAO mockProdDAO;
	StockItemDAO mockStockIDAO;
	Product p1,p;
	StockItem s1,s;
	ProductStock ps;
	@Before
	public void setUp() throws Exception {
		dao = new ProductStockDAOImpl();

		mockProdDAO = createMock(ProductDAO.class);
		mockStockIDAO = createMock(StockItemDAO.class);

		dao.setProductDAO(mockProdDAO);
		dao.setStockItemDAO(mockStockIDAO);
		p1 = new Product();
		s1 = new StockItem();

		p1.setProductID(1);
		s1.setProductID(1);
		s1.setNumInStock(1);

		String description = "Description";
		double price = 10;
		int numInStock = 1;
		String stockLocation = "StockLocation";
		String title = "Title";
		
	
		
		
		p = new Product();
		p.setTitle(title);
		p.setDescription(description);
		p.setPrice(price);
		
		s = new StockItem();
		s.setNumInStock(numInStock);
		//s.setProductID(1);
		s.setStockLocation(stockLocation);
		
		ps = new ProductStock();
		ps.setProduct(p);
		ps.setStockItem(s);
		
		
	}

	@Test
	public void testFindAllProducts()
	{
		//set up
		List<Product> retListProd = new ArrayList<Product>();
		retListProd.add(p1);
		
		//prepare mock productdao
		expect(mockProdDAO.findAllProducts()).andReturn(retListProd);
		replay(mockProdDAO);

		//prepare mock stocki-dao
		expect(mockStockIDAO.findByProductID(1)).andReturn(s1);
		replay(mockStockIDAO);

		ProductStock ps = dao.findAllProducts().get(0);
		assertEquals("Feil i integrasjon mellom stock og prod", 1, ps.getNumInStock());

		verify(mockProdDAO);
		verify(mockStockIDAO);

	}

	@Test
	public void testFindbyProductIDSuccess()
	{
		//check for success
		expect(mockProdDAO.findByProductID(1)).andReturn(p1);
		replay(mockProdDAO);

		expect(mockStockIDAO.findByProductID(1)).andReturn(s1);
		replay(mockStockIDAO);

		ProductStock ps = dao.findByProductID(1);
		assertEquals("Feil i integrasjon mellom stock og prod", 1, ps.getNumInStock());

		verify(mockProdDAO);
		verify(mockStockIDAO);

	}

	@Test
	public void testFindByProductIDFail()
	{
		//check for failure

		expect(mockProdDAO.findByProductID(1)).andReturn(null);
		replay(mockProdDAO);
		expect(mockStockIDAO.findByProductID(1)).andReturn(null);
		replay(mockStockIDAO);

		assertNull("Skulle vært null", dao.findByProductID(1));
		verify(mockProdDAO);
		verify(mockStockIDAO);
	}

	@Test
	public void testInsertProductStock(){
		//prep

		
		expect(mockProdDAO.insertProduct(p)).andReturn(1);
		mockStockIDAO.insertStockItem(s);
		
		
		replay(mockProdDAO);
		replay(mockStockIDAO);
		
		assertEquals("Feil i productID", 1, dao.insertProduct(ps));
		
		verify(mockProdDAO);
		verify(mockStockIDAO);
		
		
	}

	//TODO: refactor til tre forskjellige metoder.
	@Test//(expected=NoSuchElementException.class)
	public void testRemoveProduct() {
	
		expect(mockStockIDAO.findByProductID(s.getProductID())).andReturn(s);
		expect(mockStockIDAO.findByProductID(s.getProductID())).andReturn(null);
		expect(mockStockIDAO.findByProductID(s.getProductID())).andReturn(s);
		
		
		mockStockIDAO.removeStockItem(s);
		mockProdDAO.removeProduct(p);
		mockProdDAO.removeProduct(p);
		expectLastCall().andThrow(new NoSuchElementException());
		
		replay(mockStockIDAO);
		replay(mockProdDAO);
		
		dao.removeProduct(ps);
		
		try {
			dao.removeProduct(ps);
			fail();
		} catch (NoSuchElementException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
		}
		
		try{
			dao.removeProduct(ps);
			fail();
		}
		catch (NoSuchElementException e) {
			// TODO: handle exception
		}
		
		verify(mockProdDAO);
		verify(mockStockIDAO);
				
	}
	
	@Test
	public void testUpdateProductSuccess() {
		
		expect(mockStockIDAO.findByProductID(s.getProductID())).andReturn(s);
		mockProdDAO.updateProduct(p);
		mockStockIDAO.updateStockItem(s);
		
		
		replay(mockStockIDAO);
		replay(mockProdDAO);
		
		dao.updateProduct(ps);
		
		verify(mockProdDAO);
		verify(mockStockIDAO);
	}
	
	@Test(expected=NoSuchElementException.class)
	public void testUpdateProductNoSuchStockItem() {
		expect(mockStockIDAO.findByProductID(s.getProductID())).andReturn(null);
		mockProdDAO.updateProduct(p);
		mockStockIDAO.updateStockItem(s);
		replay(mockStockIDAO);
		replay(mockProdDAO);
		
		dao.updateProduct(ps);
		
		verify(mockProdDAO);
		verify(mockStockIDAO);
	}
	
	@Test(expected=NoSuchElementException.class)
	public void testUpdateProductNoSuchProduct() {
		expect(mockStockIDAO.findByProductID(s.getProductID())).andReturn(s);
		mockProdDAO.updateProduct(p);
		expectLastCall().andThrow(new NoSuchElementException());
		replay(mockStockIDAO);
		replay(mockProdDAO);
		
		dao.updateProduct(ps);
		
		verify(mockProdDAO);
		verify(mockStockIDAO);
	}
	
	
}
